/************************************************************************
                                                                     
   Xceed Ultimate ListBox for Silverlight                                                                                                                                            
   Copyright (C) 2010 Xceed Software Inc.    
                                                                     
   This program is provided to you under the terms of the GNU General Public  
   License version 2 as published by the Free Software Foundation. 
        
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY, without even the implied warranty of 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License along 
   with this program, if not, write to the Free Software Foundation, Inc., 
   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

   This program can be provided to you by Xceed Software Inc. under a
   proprietary commercial license agreement for use in non-Open Source
   projects. Visit Xceed.com to find the commercial edition of 
   Xceed Ultimate ListBox for Silverlight.                                    
                                                                      
 **********************************************************************/

using System;
using System.ComponentModel;

namespace Xceed.Silverlight.Data
{
  internal abstract class ParentHelper<T> : IDataHelper<T>
  {
    internal ParentHelper( IDataHelper childHelper )
    {
      if( childHelper == null )
        throw new ArgumentNullException( "childHelper" );

      m_childHelper = childHelper;
    }


    public SortDescription[] CompleteSort
    {
      get
      {
        return this.ChildHelper.CompleteSort;
      }
    }


    #region ChildHelper Property

    internal IDataHelper ChildHelper
    {
      get
      {
        return m_childHelper;
      }
    }

    private IDataHelper m_childHelper; //null

    #endregion ChildHelper Property


    internal virtual object ConvertLocal( object item )
    {
      return item;
    }

    internal virtual object ConvertBackLocal( object item )
    {
      return item;
    }


    protected static Nullable<int> HandleSourcePositions( ref object firstItem, ref object secondItem )
    {
      Nullable<int> compareResult = null;

      if( object.ReferenceEquals( firstItem, secondItem ) )
      {
        return 0;
      }

      SourcePosition firstSourcePosition = firstItem as SourcePosition;
      SourcePosition secondSourcePosition = secondItem as SourcePosition;

      if( firstSourcePosition != null )
      {
        if( firstSourcePosition.IsBeforeFirst )
        {
          compareResult = -1;
        }
        else if( firstSourcePosition.IsAfterLast )
        {
          compareResult = 1;
        }
        else if( firstSourcePosition is ItemPosition )
        {
          firstItem = ( ( ItemPosition )firstSourcePosition ).Item;
        }
      }

      if( secondSourcePosition != null )
      {
        if( secondSourcePosition.IsBeforeFirst )
        {
          compareResult = 1;
        }
        else if( secondSourcePosition.IsAfterLast )
        {
          compareResult = -1;
        } 
        else if( secondSourcePosition is ItemPosition )
        {
          secondItem = ( ( ItemPosition )secondSourcePosition ).Item;
        }
      }

      return compareResult;
    }


    #region IDataHelper Members

    public virtual T ConvertItem( object value )
    {
      return ( T )this.Convert( value );
    }

    public virtual object ConvertBackItem( T value )
    {
      return this.ConvertBack( value );
    }

    public virtual object Convert( object value )
    {
      object childValue = this.ChildHelper.Convert( value );

      return this.ConvertLocal( childValue );
    }

    public virtual object ConvertBack( object value )
    {
      object convertedValue = this.ConvertBackLocal( value );

      return this.ChildHelper.ConvertBack( convertedValue );
    }

    public virtual object GetMemberValue( string memberName, object item )
    {
      object convertedItem = this.ConvertBackLocal( item );

      return m_childHelper.GetMemberValue( memberName, convertedItem );
    }

    public virtual bool TryGetMemberValue( string memberName, object item, out object value )
    {
      object convertedItem = this.ConvertBackLocal( item );

      return this.ChildHelper.TryGetMemberValue( memberName, convertedItem, out value );
    }

    public virtual int Compare( object firstItem, object secondItem )
    {
      object firstConvertedItem = this.ConvertBackLocal( firstItem );
      object secondConvertedItem = this.ConvertBackLocal( secondItem );

      return this.ChildHelper.Compare( firstConvertedItem, secondConvertedItem );
    }

    public virtual int CompareValues( object firstValue, object secondValue, string propertyName )
    {
      return this.ChildHelper.CompareValues( firstValue, secondValue, propertyName );
    }

    public void InvalidateItem( object item )
    {
      if( item is T )
      {
        this.InvalidateItem( ( T )item );
      }
    }

    public virtual void InvalidateItem( T item )
    {
      object baseItem;

      try
      {
        baseItem = this.ConvertBackLocal( item );
      }
      catch( Exception )
      {
        // The item cannot be invalidated if it isn't of the appropriate type.
        return;
      }

      this.ChildHelper.InvalidateItem( baseItem );
    }

    #endregion IDataHelper Members
  }
}
